package com.dream.xcarrecorder.rec;

import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaFormat;

import androidx.collection.ArraySet;

import com.dream.libxrec.encode.audio.AACEncoder;
import com.dream.libxrec.encode.audio.IAudioEncoder;
import com.dream.libxrec.encode.audio.IAudioEncoderListener;
import com.dream.libxrec.sound.ISoundRec;
import com.dream.libxrec.sound.XAudioRecord;

import java.nio.ByteBuffer;

/**
 * 由于Android的麦克风一般只有一个，如果需要多路摄像头录像且有声音，或者多个地方需要用到，
 * 一般就需要在一个地方实现并进行分发。
 *
 * 实现为单例
 */
public class AudioHelper {
    private Context mContext = null;
    private ISoundRec mSoundRec = null;//录音机
    private final ArraySet<ISoundRecListener> mRecCB =
            new ArraySet<>();
    private final ArraySet<IAudioEncoderListener> mEncoderCB =
            new ArraySet<>();

    private MediaFormat mAudioFormat = null;

    private IAudioEncoder mAudioEncoder = null;

    private static final int AUDIO_SAMPLE_RATE = 8000;//采样率
    private static final int AUDIO_BIT_RATE = 8000;//比特率
    private static final int AUDIO_CHANNEL_NUM = 1;//通道数

    private AudioHelper() {}

    public static AudioHelper getInstance() {
        return SingletonHolder.sInstance;
    }

    private static class SingletonHolder{
        private static final AudioHelper sInstance = new  AudioHelper();
    }

    private final ISoundRec.ISoundRecListener mSoundRecListener =
            new ISoundRec.ISoundRecListener(){
                @Override
                public void onSoundRec(byte[] pcm, int size) {
                    for (ISoundRecListener listener:mRecCB){
                        try {
                            listener.onSoundRec(pcm,size);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    if (mAudioEncoder != null){
                        mAudioEncoder.encode(pcm,0,size);
                    }
                }
            };

    private final IAudioEncoderListener mSoundEncoder = new IAudioEncoderListener() {
        @Override
        public void onFormat(MediaFormat format) {
            mAudioFormat = format;
            for (IAudioEncoderListener listener:mEncoderCB){
                try {
                    listener.onFormat(format);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFrame(ByteBuffer buffer, MediaCodec.BufferInfo info) {
            for (IAudioEncoderListener listener:mEncoderCB){
                try {
                    listener.onFrame(buffer,info);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFrame(byte[] buffer, int size,long pts) {
            for (IAudioEncoderListener listener:mEncoderCB){
                try {
                    listener.onFrame(buffer,size,pts);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    };

    public void init(Context ct){
        this.mContext = ct;
        mAudioEncoder = new AACEncoder().init(mContext,
                AUDIO_SAMPLE_RATE,AUDIO_BIT_RATE,AUDIO_CHANNEL_NUM,
                AACEncoder.AAC_PROFILE_LEVEL_LC);
        mAudioEncoder.addIEncoderListener(mSoundEncoder);
        mSoundRec = new XAudioRecord().init(mContext,
                AUDIO_SAMPLE_RATE,AUDIO_CHANNEL_NUM,16,null);
        mSoundRec.setISoundRecListener(mSoundRecListener);

    }

    /**
     * 设置音频原始数据监听
     * @param listener
     */
    public void addPCMListener(ISoundRecListener listener){
        if (listener == null){
            return;
        }
        mRecCB.add(listener);
    }

    /**
     * 取消监听
     * @param listener
     */
    public void removePCMListener(ISoundRecListener listener){
        if (listener == null){
            return;
        }
        mRecCB.add(listener);
    }

    /**
     * 监听编码后的数据回调
     * @param listener
     */
    public void addListener(IAudioEncoderListener listener){

        if (listener == null){
            return;
        }

        if (mAudioFormat != null){
            listener.onFormat(mAudioFormat);
        }

        mEncoderCB.add(listener);
    }

    /**
     * 取消监听
     * @param listener
     */
    public void removeListener(IAudioEncoderListener listener){
        if (listener == null){
            return;
        }

        mEncoderCB.remove(listener);
    }

    public synchronized boolean isRun() {
        if (mSoundRec == null||mAudioEncoder == null){
            return false;
        }
        return mSoundRec.isRun()&&mAudioEncoder.isRun();
    }

    public synchronized void start() {
        if (mAudioEncoder != null){
            mAudioEncoder.start();
        }

        if (mSoundRec != null){
            mSoundRec.start();
        }
    }
    public synchronized void stop() {
        if (mSoundRec != null){
            mSoundRec.stop();
        }

        if (mAudioEncoder != null){
            mAudioEncoder.stop();
        }

        mEncoderCB.clear();
    }

    public interface ISoundRecListener{
        public void onSoundRec(byte[] pcm,int size);
    }

}
